/**
 * Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.springBoot.springBootSysCore.modules.entity.utils;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.springBoot.springBootSysCore.filter.CustomHttpServletResponse;
import com.springBoot.springBootSysCore.modules.entity.system.SysResource;
import com.springBoot.springBootSysCore.modules.entity.system.SysUser;
import com.springBoot.springBootSysCore.modules.repository.system.SysLogRepository;
import com.springBoot.springBootSysCore.modules.repository.system.SysResourceRepository;
import com.springBoot.springBootSysCore.modules.services.SystemService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.method.HandlerMethod;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.springBoot.springBootSysCore.common.config.Global;
import com.springBoot.springBootSysCore.common.utils.CacheUtils;
import com.springBoot.springBootSysCore.common.utils.Exceptions;
import com.springBoot.springBootSysCore.common.utils.SpringContextHolder;
import com.springBoot.springBootSysCore.common.utils.StringUtils;
import com.springBoot.springBootSysCore.modules.entity.system.SysLog;

/**
 * 字典工具类
 * @author ThinkGem
 * @version 2014-11-7
 */
public class LogUtils {

	public static final String CACHE_MENU_NAME_PATH_MAP = "menuNamePathMap";

	private static SysLogRepository sysLogRepository = SpringContextHolder.getBean(SysLogRepository.class);
	private static SysResourceRepository sysResourceRepository = SpringContextHolder.getBean(SysResourceRepository.class);
	private static SystemService systemService = SpringContextHolder.getBean(SystemService.class);

	/**
	 * 保存日志
	 */
	public static void saveLog(HttpServletRequest request, String title){
		saveLog(request,null, null, null, title);
	}

	/**
	 * 保存日志
	 */
	@Transactional
	public static void saveLog(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex, String title){
		SysUser user = UserUtils.getUser();
//		if (user != null && user.getId() != null){
//		if (user != null){
			SysLog log = new SysLog();
			log.setTitle(title);
			log.setType(ex == null ? SysLog.TYPE_ACCESS : SysLog.TYPE_EXCEPTION);
			log.setRemoteAddr(StringUtils.getRemoteAddr(request));
			log.setUserAgent(request.getHeader("user-agent"));
			log.setRequestUri(request.getRequestURI());
			log.setParams(request.getParameterMap());
			log.setMethod(request.getMethod());
//			if (StringUtils.isBlank(Exceptions.getStackTraceAsString(ex))){
//				CustomHttpServletResponse cresponse=new CustomHttpServletResponse((HttpServletResponse)response);
//				try {
//					log.setRespos(new String(cresponse.getCopy(),response.getCharacterEncoding()));
//				} catch (UnsupportedEncodingException e) {
//					e.printStackTrace();
//				}
//			}
			// 异步保存日志
			new SaveLogThread(log, handler, ex).start();
//		}
//		}
	}

	/**
	 * 保存日志线程
	 */
	public static class SaveLogThread extends Thread{

		private SysLog log;
		private Object handler;
		private Exception ex;

		public SaveLogThread(SysLog log, Object handler, Exception ex){
			super(SaveLogThread.class.getSimpleName());
			this.log = log;
			this.handler = handler;
			this.ex = ex;
		}

		@Override
		public void run() {
			// 获取日志标题
			if (StringUtils.isBlank(log.getTitle())){
				String permission = "";
				if (handler instanceof HandlerMethod){
					Method m = ((HandlerMethod)handler).getMethod();
					RequiresPermissions rp = m.getAnnotation(RequiresPermissions.class);
					permission = (rp != null ? StringUtils.join(rp.value(), ",") : "");
				}
				log.setTitle(getMenuNamePath(log.getRequestUri(), permission));
			}
			// 如果有异常，设置异常信息
			log.setException(Exceptions.getStackTraceAsString(ex));
			// 如果无标题并无异常日志，则不保存信息
			if (StringUtils.isBlank(log.getTitle()) && StringUtils.isBlank(log.getException())){
				return;
			}
			// 保存日志信息
			log.preInsert();
            sysLogRepository.save(log);
		}
	}

	/**
	 * 获取菜单名称路径（如：系统设置-机构用户-用户管理-编辑）
	 */
	public static String getMenuNamePath(String requestUri, String permission){
		String href = StringUtils.substringAfter(requestUri, Global.getAdminPath());
		@SuppressWarnings("unchecked")
		Map<String, String> menuMap = (Map<String, String>)CacheUtils.get(CACHE_MENU_NAME_PATH_MAP);
		if (menuMap == null){
			menuMap = Maps.newHashMap();
			List<SysResource> menuList = systemService.getAllOfPrent();
			for (SysResource menu : menuList){
				// 获取菜单名称路径（如：系统设置-机构用户-用户管理-编辑）
				String namePath = "";
				if (menu.getChildrenResource() != null){
					List<String> namePathList = Lists.newArrayList();
					for (SysResource resource : menu.getChildrenResource()){
						if (SysResource.getRootId().equals(resource.getId())){//id为1
							continue; // 过滤跟节点
						}
						for (SysResource m : menuList){
							if (m.getId().equals(resource.getId())){
								namePathList.add(m.getName());
								break;
							}
						}
					}
					namePathList.add(menu.getName());
					namePath = StringUtils.join(namePathList, "-");
				}
				// 设置菜单名称路径
				if (StringUtils.isNotBlank(menu.getUrl())){
					menuMap.put(menu.getUrl(), namePath);
				}else if (StringUtils.isNotBlank(menu.getCode())){
					for (String p : StringUtils.split(menu.getCode())){
						menuMap.put(p, namePath);
					}
				}

			}
			CacheUtils.put(CACHE_MENU_NAME_PATH_MAP, menuMap);
		}
		String menuNamePath = menuMap.get(href);
		if (menuNamePath == null){
			for (String p : StringUtils.split(permission)){
				menuNamePath = menuMap.get(p);
				if (StringUtils.isNotBlank(menuNamePath)){
					break;
				}
			}
			if (menuNamePath == null){
				return "";
			}
		}
		return menuNamePath;
	}


}
